package activity

import (
	"context"
	// "fmt"

	"mall/common/globalkey"
	"mall/common/resultx"
	enum "mall/service/backend/common/enum/promotion"
	"mall/service/promotion/model"
	"mall/service/promotion/rpc/internal/svc"
	"mall/service/promotion/rpc/types/promotion"

	// "github.com/sirupsen/logrus"
	"github.com/zeromicro/go-zero/core/logx"
)

type CheckActivityScopeLogic struct {
	ctx    context.Context
	svcCtx *svc.ServiceContext
	logx.Logger
}

func NewCheckActivityScopeLogic(ctx context.Context, svcCtx *svc.ServiceContext) *CheckActivityScopeLogic {
	return &CheckActivityScopeLogic{
		ctx:    ctx,
		svcCtx: svcCtx,
		Logger: logx.WithContext(ctx),
	}
}

func (l *CheckActivityScopeLogic) CheckActivityScope(
	in *promotion.CheckActivityScopeReq,
) (*promotion.ActivityRelationshipInfo, error) {
	// logrus.Info(fmt.Sprintf("CheckActivityScopeReq: %+v", in))
	logx.Infof("CheckActivityScope : %+v ", in)

	if in.ActivityId == 0 || len(in.Skus) == 0 {
		return nil, resultx.NewErrCode(resultx.REUQEST_PARAM_ERROR)
	}

	data, err := l.svcCtx.Activity.FindOne(l.ctx, in.ActivityId)
	if err != nil {
		return nil, resultx.NewErrCode(resultx.ACTIVITY_ID_INVALID)
	}

	if data.ActivityType != enum.PromotionActivityDiscount && data.ActivityType != enum.PromotionActivityMember && data.ActivityType != enum.PromotionActivityCharge {
		return nil, resultx.NewErrCode(resultx.ACTIVITY_ID_INVALID)
	}

	resp := &promotion.ActivityRelationshipInfo{}
	switch data.ScopeType {
	case enum.PromotionScopeAll:
		return resp, nil
	case enum.PromotionScopeCategory:
		var categoryIds []any
		cidMap := make(map[uint64]struct{})
		categoryIdSkuIdMap := make(map[uint64][]uint64)
		for _, v := range in.Skus {
			if v.VariationId != nil && *v.VariationId > 0 && len(v.CategoryIds) > 0 {
				for _, cid := range v.CategoryIds {
					categoryIdSkuIdMap[cid] = append(categoryIdSkuIdMap[cid], *v.VariationId)
					if _, ok := cidMap[cid]; !ok {
						categoryIds = append(categoryIds, cid)
						cidMap[cid] = struct{}{}
					}
				}
			}
		}
		resp, err = l.checkActivityProductCategoryScope(in.ActivityId, categoryIds, categoryIdSkuIdMap)
	case enum.PromotionScopeBrand:
		var brandIds []any
		bidMap := make(map[uint64]struct{})
		brandIdSkuIdMap := make(map[uint64][]uint64)
		for _, v := range in.Skus {
			if v.VariationId != nil && *v.VariationId > 0 && v.BrandId != nil && *v.BrandId > 0 {
				brandIdSkuIdMap[*v.BrandId] = append(brandIdSkuIdMap[*v.BrandId], *v.VariationId)
				if _, ok := bidMap[*v.BrandId]; !ok {
					brandIds = append(brandIds, *v.BrandId)
					bidMap[*v.BrandId] = struct{}{}
				}
			}
		}
		resp, err = l.checkActivityProductBrandScope(in.ActivityId, brandIds, brandIdSkuIdMap)
	case enum.PromotionScopeProduct:
		var skuIds []any
		skuIdMap := make(map[uint64]struct{})
		for _, v := range in.Skus {
			if v.VariationId != nil && *v.VariationId > 0 {
				if _, ok := skuIdMap[*v.VariationId]; !ok {
					skuIds = append(skuIds, *v.VariationId)
					skuIdMap[*v.VariationId] = struct{}{}
				}
			}
		}
		resp, err = l.checkActivityProductScope(in.ActivityId, skuIds)
	}
	if err != nil {
		return nil, err
	}

	return resp, nil
}

func (l *CheckActivityScopeLogic) checkActivityProductScope(
	activityId uint64,
	skuIds []any,
) (*promotion.ActivityRelationshipInfo, error) {
	if len(skuIds) == 0 {
		return &promotion.ActivityRelationshipInfo{
			ActivityId: activityId,
		}, nil
	}

	filterMap := make(map[string]map[string][]any)
	filterMap[model.PromotionActivityProductRelationshipColumns.ActivityID] = map[string][]any{
		"equalTo": {activityId},
	}
	filterMap[model.PromotionActivityProductRelationshipColumns.ProductType] = map[string][]any{
		"equalTo": {enum.PromotionActivityProductOther},
	}
	filterMap[model.PromotionActivityProductRelationshipColumns.Status] = map[string][]any{
		"equalTo": {globalkey.StatusEnabled},
	}
	filterMap[model.PromotionActivityProductRelationshipColumns.SkuID] = map[string][]any{
		"in": skuIds,
	}
	res, _, err := l.svcCtx.Activity.GetProductList(l.ctx, model.M{}, -1, filterMap)
	if err != nil {
		return nil, err
	}

	resp := &promotion.ActivityRelationshipInfo{
		ActivityId: activityId,
	}
	for _, v := range res {
		resp.SkuIds = append(resp.SkuIds, v.SkuID)
	}

	return resp, nil
}

func (l *CheckActivityScopeLogic) checkActivityProductBrandScope(
	activityId uint64,
	brandIds []any,
	brandIdSkuIdMap map[uint64][]uint64,
) (*promotion.ActivityRelationshipInfo, error) {
	if len(brandIds) == 0 {
		return &promotion.ActivityRelationshipInfo{
			ActivityId: activityId,
		}, nil
	}

	filterMap := make(map[string]map[string][]any)
	filterMap[model.PromotionActivityProductBrandRelationshipColumns.ActivityID] = map[string][]any{
		"equalTo": {activityId},
	}
	filterMap[model.PromotionActivityProductBrandRelationshipColumns.Status] = map[string][]any{
		"equalTo": {globalkey.StatusEnabled},
	}
	filterMap[model.PromotionActivityProductBrandRelationshipColumns.ProductBrandID] = map[string][]any{
		"in": brandIds,
	}
	res, _, err := l.svcCtx.Activity.GetProductBrandList(l.ctx, model.M{}, -1, filterMap)
	if err != nil {
		return nil, err
	}

	resp := &promotion.ActivityRelationshipInfo{
		ActivityId: activityId,
	}
	for _, v := range res {
		if skuIds, ok := brandIdSkuIdMap[v.ProductBrandID]; ok {
			resp.SkuIds = append(resp.SkuIds, skuIds...)
		}
	}

	return resp, nil
}

func (l *CheckActivityScopeLogic) checkActivityProductCategoryScope(
	activityId uint64,
	categoryIds []any,
	categoryIdSkuIdMap map[uint64][]uint64,
) (*promotion.ActivityRelationshipInfo, error) {
	if len(categoryIds) == 0 {
		return &promotion.ActivityRelationshipInfo{
			ActivityId: activityId,
		}, nil
	}

	filterMap := make(map[string]map[string][]any)
	filterMap[model.PromotionActivityProductCategoryRelationshipColumns.ActivityID] = map[string][]any{
		"equalTo": {activityId},
	}
	filterMap[model.PromotionActivityProductCategoryRelationshipColumns.Status] = map[string][]any{
		"equalTo": {globalkey.StatusEnabled},
	}
	filterMap[model.PromotionActivityProductCategoryRelationshipColumns.ProductCategoryID] = map[string][]any{
		"in": categoryIds,
	}
	res, _, err := l.svcCtx.Activity.GetProductCategoryList(l.ctx, model.M{}, -1, filterMap)
	if err != nil {
		return nil, err
	}

	resp := &promotion.ActivityRelationshipInfo{
		ActivityId: activityId,
	}
	for _, v := range res {
		if skuIds, ok := categoryIdSkuIdMap[v.ProductCategoryID]; ok {
			resp.SkuIds = append(resp.SkuIds, skuIds...)
		}
	}

	return resp, nil
}
